package com.heima.article.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.article.mapper.ApArticleConfigMapper;
import com.heima.article.mapper.ApArticleContentMapper;
import com.heima.article.mapper.ArticleHomeMapper;
import com.heima.article.service.ArticleHomeService;
import com.heima.common.exception.CustomException;
import com.heima.file.service.FileStorageService;
import com.heima.model.article.dto.ArticleDto;
import com.heima.model.article.dto.ArticleHomeDto;
import com.heima.model.article.pojo.ApArticle;
import com.heima.model.article.pojo.ApArticleConfig;
import com.heima.model.article.pojo.ApArticleContent;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.constants.ArticleConstants;
import com.heima.model.search.vo.SearchArticleVo;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @projectName: heima-leadnews
 * @package: com.heima.article.service.impl
 * @className: ArticleHomeServiceImpl
 * @author: 躺着认真玩
 * @description: 文章控制层
 * @date: 2025/5/16 0:40
 * @version: 1.0
 */
@Service
public class ArticleHomeServiceImpl extends ServiceImpl<ArticleHomeMapper,ApArticle> implements ArticleHomeService {
    @Autowired
    private ArticleHomeMapper articleHomeMapper;
    @Autowired
    private ApArticleContentMapper apArticleContentMapper;
    @Autowired
    private ApArticleConfigMapper apArticleConfigMapper;
    @Autowired
    private Configuration configuration;

    @Autowired
    private FileStorageService fileStorageService;
    @Override
    public List<ApArticle> load(ArticleHomeDto dto, Short type) {
        return articleHomeMapper.load(dto,type);

    }

    @Override
    @Transactional
    public Map submit(ArticleDto articleDto) {
        // 检查参数
        if (articleDto == null) {
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        Date date = new Date();
        Map<String, Object> map = new HashMap<>();
        if (articleDto.getId() == null) {
            // 保存文章数据
            ApArticle apArticle = BeanUtil.copyProperties(articleDto, ApArticle.class);
            apArticle.setPublishTime(date);
            this.save(apArticle);
            ApArticleContent apArticleContent = new ApArticleContent();
            apArticleContent.setArticleId(apArticle.getId());
            apArticleContent.setContent(articleDto.getContent());
            apArticleContentMapper.insert(apArticleContent);
            ApArticleConfig apArticleConfig = new ApArticleConfig();
            apArticleConfig.setArticleId(apArticle.getId());
            apArticleConfig.setIsComment(true);
            apArticleConfig.setIsForward(true);
            apArticleConfig.setIsDown(false);
            apArticleConfig.setIsDelete(false);
            apArticleConfigMapper.insert(apArticleConfig);
            map.put("articleId",apArticle.getId().toString());
            map.put("publishTime",date);
            // 生成静态模版
            try {
                handStaticUrl(articleDto.getContent(),apArticle.getId());
            } catch (Exception e) {
                throw new CustomException(AppHttpCodeEnum.STATICTEMPLATEISSUCCESSFULLYGENERATED);
            }
            return map;
        }else {

            // 修改文章
            ApArticle apArticle = BeanUtil.copyProperties(articleDto, ApArticle.class);
            apArticle.setPublishTime(date);
            this.update(apArticle,new LambdaUpdateWrapper<ApArticle>()
                    .eq(ApArticle::getId,apArticle.getId())
            );
            apArticleContentMapper.update(null,
                    new LambdaUpdateWrapper<ApArticleContent>()
                            .eq(ApArticleContent::getArticleId,articleDto.getId())
                            .set(ApArticleContent::getContent,articleDto.getContent())
            );

            apArticleConfigMapper.update(null,
                    new LambdaUpdateWrapper<ApArticleConfig>()
                            .eq(ApArticleConfig::getArticleId,articleDto.getId())
                            .set(ApArticleConfig::getIsComment,true)
                            .set(ApArticleConfig::getIsForward,true)
                            .set(ApArticleConfig::getIsDown,false)
                            .set(ApArticleConfig::getIsDelete,false)
            );
            map.put("articleId",apArticle.getId().toString());
            map.put("publishTime",date);
            // 生成静态模版
            try {
                handStaticUrl(articleDto.getContent(),apArticle.getId());
            } catch (Exception e) {
                throw new CustomException(AppHttpCodeEnum.STATICTEMPLATEISSUCCESSFULLYGENERATED);
            }
            return map;
        }

    }

    @Async
    public void handStaticUrl(String content, Long id) throws IOException, TemplateException {
        // 1.获取文章内容
        if(StringUtils.isNotBlank(content)) {
            // 2.文章内容通过freemarker生成html文件
            StringWriter out = new StringWriter();
            Template template = configuration.getTemplate("article.ftl");

            Map<String, Object> params = new HashMap<>();
            params.put("content", JSONArray.parseArray(content));

            template.process(params, out);
            InputStream is = new ByteArrayInputStream(out.toString().getBytes());

            // 3.把html文件上传到minio中
            String path = fileStorageService.uploadHtmlFile("", id + ".html", is);

            // 4.修改ap_article表，保存static_url字段
            ApArticle article = new ApArticle();
            article.setStaticUrl(path);
            articleHomeMapper.update(null, new LambdaUpdateWrapper<ApArticle>()
                    .eq(ApArticle::getId, id)
                    .set(ApArticle::getStaticUrl, path));
        //     kafka-存入到es中
            sendMessage(id);
        }
    }

    @Autowired
    private KafkaTemplate kafkaTemplate;
    private void sendMessage(Long id) {
        ApArticle apArticle = articleHomeMapper.selectById(id);
        SearchArticleVo vo = BeanUtil.copyProperties(apArticle, SearchArticleVo.class);
        try {
            kafkaTemplate.send(ArticleConstants.ARTICLE_ES_SYNC_TOPIC, JSONUtil.toJsonStr(vo));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }
}
